package cn.xinfei.xdecision.engine.runner.api;

import cn.xinfei.xdecision.common.model.enginex.po.EngineVersion;
import cn.xinfei.xdecision.constant.EngineResultEnum;
import cn.xinfei.xdecision.constant.GlobalConstant;
import cn.xinfei.xdecision.nacos.NacosSwitchProperties;
import cn.xinfei.xdecision.engine.runner.context.PipelineContextHolder;
import cn.xinfei.xdecision.engine.runner.context.XDecisionContext;
import cn.xinfei.xdecision.engine.runner.datax.DataPreCollectHandler;
import cn.xinfei.xdecision.engine.runner.datax.RiskDataApiAdapter;
import cn.xinfei.xdecision.engine.runner.executor.DecisionFlowPipeline;
import cn.xinfei.xdecision.engine.runner.executor.NodeHandler;
import cn.xinfei.xdecision.engine.runner.executor.model.StateTransmitModel;
import cn.xinfei.xdecision.engine.runner.metadata.MetadataProvider;
import cn.xinfei.xdecision.engine.runner.vo.EngineApiRequest;
import cn.xinfei.xdecision.model.DecisionApiResponse;
import com.dianping.cat.Cat;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Set;

@Slf4j
@Service
public class DecisionDecisionApi extends AbstractDecision<EngineApiRequest, DecisionApiResponse> {

    @Autowired
    private MetadataProvider metadataProvider;

    @Autowired
    private DataPreCollectHandler dataPreCollectHandler;

    @Autowired
    private NacosSwitchProperties nacosSwitchProperties;

    public DecisionApiResponse run(EngineApiRequest engineApiRequest) {
        Long start = System.currentTimeMillis();
        DecisionApiResponse engineApiResponse = new DecisionApiResponse();
        String engineCode = engineApiRequest.getEngineCode();
        String businessId = engineApiRequest.getRequestId();
        String decisionId = engineApiRequest.getDecisionId();
        engineApiResponse.setDecisionId(decisionId);
        engineApiResponse.setRequestId(businessId);
        engineApiResponse.setEngineCode(engineCode);

        Map<String, Object> fields = engineApiRequest.getIn();
        PipelineContextHolder.setRequestId(businessId);
        PipelineContextHolder.setDecisionId(decisionId);
        PipelineContextHolder.setEngineCode(engineCode);
//        PipelineContextHolder.setScene(engineApiRequest.getScene());


        try {

            log.info("执行决策流节点开始,engineCode={}", engineCode);

            EngineVersion engineVersion = metadataProvider.getEngineVersion(engineCode);
            PipelineContextHolder.setEngineCode(engineCode);
            PipelineContextHolder.setEngineVersion(engineVersion.getVersionNo() + "");
            PipelineContextHolder.setEngineName(engineVersion.getEngineName());
            engineApiResponse.setVersionNo(PipelineContextHolder.getEngineVersion());
            Map<String, NodeHandler> engineNodeMap = metadataProvider.getEngineNodeList(engineCode);
            XDecisionContext context = XDecisionContext.getContext();
            context.getPipelineMetaInfoContext().putAll(engineNodeMap);

            PipelineContextHolder.putInput(fields);
            MDC.put(GlobalConstant.NID, engineCode);


            //1.预加载变量，失败后不阻塞流程
            if (nacosSwitchProperties.isPreloadSync()) {
                Set<String> preload = DecisionFlowPipeline.preload();
                Boolean result = dataPreCollectHandler.queryFieldValue( preload, RiskDataApiAdapter.CollectTypeEnum.PRE.toString());
                if (result) {
//                throw new Exception("调用变量中心预采集接口失败");
                }
            }

            log.info("switch:" + nacosSwitchProperties);

            //2.执行决策流
            StateTransmitModel stateTransmitModel = DecisionFlowPipeline.fire();
            EngineResultEnum resultEnum = stateTransmitModel.getEngineResultEnum();
            Long step1 = System.currentTimeMillis();
            long respond = step1 - start;
            log.info("执行决策流节点结束,resultEnum={},respond={},engineCode={}", resultEnum, respond, engineCode);

            engineApiResponse.setEngineResult(resultEnum);
            engineApiResponse.setOut(PipelineContextHolder.getOut());
            engineApiResponse.setBranchRejectInfo(PipelineContextHolder.getBranchRejectInfo());
            engineApiResponse.setHitResultList(PipelineContextHolder.getHitResultList());
            engineApiResponse.setRespond(respond);
            return engineApiResponse;

        } catch (Exception e) {
            log.error("接口请求异常,PENDING,error={}", e.getMessage(), e);
            engineApiResponse.setEngineResult(EngineResultEnum.EXCEPTION_END);
            XDecisionContext.getContext().getStateContext().setEngineResultEnum(EngineResultEnum.EXCEPTION_END);
            Cat.logError(e); // 将异常上报到cat上
            return engineApiResponse;
        }
    }


}
